package com.zhangsun.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhangsun.common.bcrypt.BCryptPasswordEncoder;
import com.zhangsun.common.constant.Constant;
import com.zhangsun.expection.BusinessException;
import com.zhangsun.system.entity.UserDepartmentEntity;
import com.zhangsun.system.entity.UserEntity;
import com.zhangsun.system.entity.UserRoleEntity;
import com.zhangsun.system.mapper.UserDepartmentMapper;
import com.zhangsun.system.mapper.UserMapper;
import com.zhangsun.system.mapper.UserRoleMapper;
import com.zhangsun.system.service.UserDepartmentService;
import com.zhangsun.system.service.UserRoleService;
import com.zhangsun.system.service.UserService;
import com.zhangsun.system.vo.user.UserDisabledVo;
import com.zhangsun.system.vo.user.UserEditVo;
import com.zhangsun.system.vo.user.UserPageVo;
import com.zhangsun.system.vo.user.UserUpdatePasswordVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 用户 服务实现类
 * </p>
 *
 * @author zhangsun
 * @since 2019-07-23
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements UserService {

    @Autowired
    private UserRoleMapper userRoleMapper;

    @Autowired
    private UserDepartmentMapper userDepartmentMapper;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private UserDepartmentService userDepartmentService;

    @Override
    public Object findAll(UserPageVo vo) {
        if (!vo.getPage()) {
            return baseMapper.findAll(vo);
        }

        Page<UserEntity> page = new Page<>(vo.getCurrent(), vo.getSize());
        return baseMapper.findAll(page, vo);
    }

    @Override
    public void createAdmin() {
        checkUserUnique(Constant.ADMIN_USER_NO, null);

        UserEntity userEntity = new UserEntity();
        userEntity.setId(Constant.ADMIN_USER_ID);
        userEntity.setUserNo(Constant.ADMIN_USER_NO);
        userEntity.setName(Constant.ADMIN_USER_NO);
        userEntity.setMobile("18662910888");
        userEntity.setPassword(new BCryptPasswordEncoder().encode("123456"));
        userEntity.insert();
    }

    @Transactional
    @Override
    public void create(UserEditVo vo) {
        checkUserUnique(vo.getUserNo(), null);

        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(vo, userEntity);
        userEntity.setPassword(new BCryptPasswordEncoder().encode(vo.getPassword()));
        userEntity.insert();

        userRoleService.saveBatch(getUserRoles(userEntity.getId(), vo.getRoleIds()));
        userDepartmentService.saveBatch(getUserDepartments(userEntity.getId(), vo.getDepartmentIds()));
    }

    @Override
    public UserEntity findById(String id) {
        return baseMapper.findById(id);
    }

    @Transactional
    @Override
    public void update(String id, UserEditVo vo) {
        checkUserUnique(vo.getUserNo(), id);

        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(vo, userEntity);
        userEntity.setId(id);
        userEntity.updateById();

        LambdaQueryWrapper<UserRoleEntity> roleQueryWrapper = new QueryWrapper<UserRoleEntity>().lambda();
        roleQueryWrapper.eq(UserRoleEntity::getUserId, id);
        userRoleMapper.delete(roleQueryWrapper);
        userRoleService.saveBatch(getUserRoles(id, vo.getRoleIds()));

        LambdaQueryWrapper<UserDepartmentEntity> deptQueryWrapper = new QueryWrapper<UserDepartmentEntity>().lambda();
        deptQueryWrapper.eq(UserDepartmentEntity::getUserId, id);
        userDepartmentMapper.delete(deptQueryWrapper);
        userDepartmentService.saveBatch(getUserDepartments(id, vo.getDepartmentIds()));
    }

    private List<UserRoleEntity> getUserRoles(String userId, List<String> roleIds) {
        List<UserRoleEntity> userRoles = new ArrayList<>();
        for (String roleId : roleIds) {
            UserRoleEntity userRole = new UserRoleEntity();
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRoles.add(userRole);
        }
        return userRoles;
    }

    private List<UserDepartmentEntity> getUserDepartments(String userId, List<String> departmentIds) {
        List<UserDepartmentEntity> userDepartments = new ArrayList<>();
        for (String departmentId : departmentIds) {
            UserDepartmentEntity userDepartment = new UserDepartmentEntity();
            userDepartment.setUserId(userId);
            userDepartment.setDepartmentId(departmentId);
            userDepartments.add(userDepartment);
        }
        return userDepartments;
    }

    /**
     * 判断用户工号是否唯一
     *
     * @param userNo 用户工号
     */
    private void checkUserUnique(String userNo, String id) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda();
        queryWrapper.eq(UserEntity::getUserNo, userNo);
        if (StrUtil.isNotBlank(id)) {
            queryWrapper.ne(UserEntity::getId, id);
        }
        int count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new BusinessException("该工号已存在");
        }
    }

    @Override
    public UserEntity findByUserNo(String userNo) {
        LambdaQueryWrapper<UserEntity> queryWrapper = new QueryWrapper<UserEntity>().lambda();
        queryWrapper.eq(UserEntity::getUserNo, userNo);
        return baseMapper.selectOne(queryWrapper);
    }

    @Transactional
    @Override
    public void delete(String id) {
        baseMapper.deleteById(id);

        LambdaQueryWrapper<UserRoleEntity> roleQueryWrapper = new QueryWrapper<UserRoleEntity>().lambda();
        roleQueryWrapper.eq(UserRoleEntity::getUserId, id);
        userRoleMapper.delete(roleQueryWrapper);

        LambdaQueryWrapper<UserDepartmentEntity> deptQueryWrapper = new QueryWrapper<UserDepartmentEntity>().lambda();
        deptQueryWrapper.eq(UserDepartmentEntity::getUserId, id);
        userDepartmentMapper.delete(deptQueryWrapper);
    }

    @Override
    public void updatePassword(String id, UserUpdatePasswordVo vo) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(id);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        userEntity.setPassword(bCryptPasswordEncoder.encode(vo.getPassword()));
        userEntity.updateById();
    }

    @Override
    public void updateDisabled(String id, UserDisabledVo vo) {
        UserEntity userEntity = new UserEntity();
        userEntity.setId(id);
        userEntity.setDisabled(vo.getDisabled());
        userEntity.updateById();
    }

}
